package com.umessage.common.util;

import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.Socket;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;

/**
 * @author 吃喝玩乐小天王
 * @info 工具类，提供一些算法，排序，矩阵转秩，唯一KEY，乱序等
 * @email 1066031245@qq.com
 */
public class Atools {
	// 获得当前的时间 11:9:7
	public static String getNowTime(String fmt) {
		SimpleDateFormat sdf = new SimpleDateFormat(fmt);
		return sdf.format(new Date());
	}

	public static String getCodeFromObject(Object... objs) {
		String str = "";
		for (int i = 0; i < objs.length; i++) {
			if (null != objs[i])
				str += objs[i].hashCode();
		}
		return Atools.encode64(str);
	}

	/**
	 * @info 获得顶级域名
	 * @param url
	 * @return
	 */
	public static String getTopDomain(String url) {
		Pattern p = Pattern.compile("(?<=//|)((\\w)+\\.)+\\w+");
		Matcher m = p.matcher(url);
		if (m.find()) {
			return m.group();
		} else {
			return null;
		}
	}

	public static String getDoubleStr(String str) {
		Pattern p = Pattern.compile("[\\d]+.[0-9]*");
		Matcher m = p.matcher(str);
		if (m.find()) {
			return m.group();
		} else {
			return null;
		}
	}

	public static boolean isNotEmpty(String str) {
		if (null != str && str.length() > 0) {
			return true;
		}
		return false;
	}
	
	public static boolean isEmpty(String str) {
		
		return !isNotEmpty(str);
	}

	/**
	 * @info 手机号码验证
	 */
	public static boolean chkPhone(String s) {
		// |(15[^4,\\D])|(18[0,5-9])
		Pattern p = Pattern.compile("^(1[3,5,7,8][0-9])\\d{8}$");
		Matcher m = p.matcher(s);
		return m.matches();
	}

	/**
	 * @info 电话号码验证
	 */
	public static boolean chkTel(String s) {
		// |(15[^4,\\D])|(18[0,5-9])
		Pattern p = Pattern.compile("^0\\d{2,3}-\\d{7,8}$");
		Matcher m = p.matcher(s);
		return m.matches();
	}

	/**
	 * @info 邮箱验证
	 */
	public static boolean chkEmail(String s) {
		// |(15[^4,\\D])|(18[0,5-9])
		Pattern p = Pattern.compile("^/w+([-.]/w+)*@/w+([-]/w+)*/.(/w+([-]/w+)*/.)*[a-z]{2,3}$");
		Matcher m = p.matcher(s);
		return m.matches();
	}

	/**
	 * @info 将字符串以特定的分隔符解析成线性表
	 */
	public static List<String> parseStr2List(String str, String regex) {
		List<String> lists = new ArrayList<String>();
		if (isNotEmpty(str)) {
			String ss[] = str.split(regex);
			if (ss.length > 0) {
				for (int i = 0; i < ss.length; i++) {
					if (isNotEmpty(ss[i]))
						lists.add(ss[i]);
				}
			}
		}
		return lists;
	}
	
	/**
	 * 字节数据转十六进制字符串
	 * 
	 * @param bytes
	 * @return
	 */
	public static String bytes2Hex(byte[] bytes) {
		if (bytes == null || bytes.length == 0) {
			return null;
		}

		BigInteger bi = new BigInteger(1, bytes);
		String hex = bi.toString(16);
		int paddingLength = (bytes.length * 2) - hex.length();
		if (paddingLength > 0) {
			return String.format("%0" + paddingLength + "d", 0) + hex;
		} else {
			return hex;
		}
	}

	public static String getOneStr() {
		String str = UUID.randomUUID().toString().replaceAll("-", "");
		return str.toLowerCase();
	}

	public static <T> List<T> str2List(String dataStr, String splitStr, Class<T> cls) {
		String[] ss = dataStr.split(splitStr);
		List<T> list = new ArrayList<T>();
		for (String s : ss) {
			if (!isEmpty(s)) {
				String type = cls.getSimpleName();
				if ("Integer".equals(type)) {
					Integer i = Integer.parseInt(s);
					list.add(cls.cast(i));
				}
				if ("Long".equals(type)) {
					Long i = Long.parseLong(s);
					list.add(cls.cast(i));
				}
				if ("Double".equals(type)) {
					Double i = Double.parseDouble(s);
					list.add(cls.cast(i));
				}
				if ("Boolean".equals(type)) {
					Boolean i = Boolean.parseBoolean(s);
					list.add(cls.cast(i));
				}
				if ("String".equals(type)) {
					list.add(cls.cast(s));
				}

			}
		}
		return list;
	}

	public static String list2Str(List<?> lists) {
		StringBuilder sb = new StringBuilder();
		if (lists.size() > 0) {
			for (Object o : lists) {
				sb.append(o).append(",");
			}
			String res = sb.toString();
			if (res != null && res.length() > 0) {
				return res.substring(0, res.length() - 1);
			}
		}
		return null;
	}

	public static String map2Str(Map<?, ?> map) {
		StringBuilder sb = new StringBuilder();
		if (!map.isEmpty()) {
			for (Entry<?, ?> e : map.entrySet()) {
				sb.append(e.getKey()).append(":").append(e.getValue()).append(",");
			}
			String res = sb.toString();
			if (res != null && res.length() > 0) {
				return res.substring(0, res.length() - 1);
			}
		}
		return null;
	}

	public static Map<String, String> str2Map(String dataStr) {
		Map<String, String> map = new HashMap<String, String>();
		String[] ss = dataStr.split(",");
		for (String s : ss) {
			if (!isEmpty(s)) {
				String[] kv = s.split(":");
				map.put(kv[0], kv[1]);
			}
		}
		return map;
	}

	/**
	 * @info 将字符串以特定的分隔符解析成线性表
	 */
	public static List<String> str2List(String str, String regex) {
		List<String> lists = new ArrayList<String>();
		if (isNotEmpty(str)) {
			String ss[] = str.split(regex);
			if (ss.length > 0) {
				for (int i = 0; i < ss.length; i++) {
					if (isNotEmpty(ss[i]))
						lists.add(ss[i]);
				}
			}
		}
		return lists;
	}

	/**
	 * A method for output the ride table.<br>
	 */
	public static void multiplicationTable() {
		for (int i = 1; i <= 9; i++) {
			for (int j = 1; j <= i; j++) {
				System.out.print(i + "*" + j + "=");
				if (i * j < 10)
					System.out.print(" ");
				System.out.print(i * j + "\t");
			}
			System.out.println();
		}
	}

	/**
	 * The classical sort of bubble
	 * 
	 * @0,每一次比较相邻的元素,把大的交换放在这个的后面 @1,[2,6,1,5,7] @2,[2,1,5,6|7] 1 @3,[1,2,5|6,7]
	 *                            2 @4,[1,2|5,6,7] 3 @5,[1|2,5,6,7] 4 @6
	 *                            i用来标记最大的比较次数,为数组长度-1的值 @7
	 *                            j是标记每循环一次,元素比较的次数,每次比较相邻的元素大小,所以下一次循环时,
	 *                            比较次数就会减少一次,直到为0次
	 */
	public static int[] classicsBubble(int[] array) {
		for (int i = 0; i < array.length - 1; i++) {
			for (int j = 0; j < array.length - i - 1; j++) {
				if (array[j] > array[j + 1]) {
					int tmp = array[j];
					array[j] = array[j + 1];
					array[j + 1] = tmp;
				}
			}
		}
		return array;
	}

	/**
	 * 改进的冒泡排序算法
	 * 
	 * @param table
	 */
	public static void bubbleSort(int[] table) // 冒泡排序
	{
		boolean exchange = true; // 是否交换的标记
		for (int i = 1; i < table.length && exchange; i++) // 有交换时再进行下一趟，最多n-1趟
		{
			exchange = false; // 假定元素未交换
			for (int j = 0; j < table.length - i; j++) {
				// 一次比较、交换
				if (table[j] > table[j + 1]) // 反序时，交换
				{
					int temp = table[j];
					table[j] = table[j + 1];
					table[j + 1] = temp;
					exchange = true; // 有交换
				}
			}
		}
	}

	/**
	 * selectSort use select method sort the array
	 */
	public static void selectSort(int[] table) {
		// 直接选择排序
		for (int i = 0; i < table.length - 1; i++) {// n-1趟排序
			// 每趟在从table[i]开始的子序列中寻找最小元素
			int min = i; // 设第i个数据元素最小
			for (int j = i + 1; j < table.length; j++)
				// 在子序列中查找最小值
				if (table[j] < table[min])
					min = j; // 记住最小元素下标

			if (min != i) // 将本趟最小元素交换到前边
			{
				int temp = table[i];
				table[i] = table[min];
				table[min] = temp;
			}
		}
	}

	/**
	 * 
	 * @param a
	 * @return
	 */
	public static int[] classicsSelectSort(int a[]) {
		for (int i = 0; i < a.length - 1; i++) {
			for (int j = i + 1; j < a.length; j++) {
				if (a[i] > a[j]) {
					int tmp = a[i];
					a[i] = a[j];
					a[j] = tmp;
				}
			}
		}
		return a;
	}

	/**
	 * insertSort use insert methed sort the array
	 */
	public static void insertSort1(int[] table) { // 直接插入排序
		// 数组是引用类型，元素值将被改变
		for (int i = 1; i < table.length; i++) {// n-1趟扫描
			int temp = table[i], j; // 每趟将table[i]插入到前面已排序的序列中
			for (j = i - 1; j > -1 && temp < table[j]; j--) // 将前面较大元素向后移动
			{
				table[j + 1] = table[j];
			}
			table[j + 1] = temp;
		}
	}

	/**
	 * 
	 * @param n
	 * @return
	 */
	public static int[] classicsInsertSort1(int n[]) {
		for (int i = 1; i < n.length; i++) {
			for (int j = i - 1; j >= 0 && n[j] > n[j + 1]; j--) {
				if (n[j] > n[j + 1]) {
					int tmp = n[j + 1];
					n[j + 1] = n[j];
					n[j] = tmp;
				}
			}
		}
		return n;
	}

	/**
	 * quickSort use the most little time sort the array
	 */
	public static void quickSort(int[] table) // 快速排序
	{
		quickSort(table, 0, table.length - 1);
	}

	// 一趟快速排序，递归算法
	private static void quickSort(int[] table, int low, int high) {
		// low、high指定序列的下界和上界
		if (low < high) // 序列有效
		{
			int i = low, j = high;
			int vot = table[i]; // 第一个值作为基准值
			while (i != j) // 一趟排序
			{
				while (i < j && vot <= table[j])
					// 从后向前寻找较小值
					j--;
				if (i < j) {
					table[i] = table[j]; // 较小元素向前移动
					i++;
				}
				while (i < j && table[i] < vot)
					// 从前向后寻找较大值
					i++;
				if (i < j) {
					table[j] = table[i]; // 较大元素向后移动
					j--;
				}
			}
			table[i] = vot; // 基准值的最终位置
			quickSort(table, low, j - 1); // 前端子序列再排序
			quickSort(table, i + 1, high); // 后端子序列再排序
		}
	}

	/**
	 * @info 将一个序列化的对象写入文件中保存
	 * @param obj
	 */
	public static void writeObjectToFile(Object obj, String fileName) {
		File file = new File(fileName);
		FileOutputStream out;
		try {
			out = new FileOutputStream(file);
			ObjectOutputStream objOut = new ObjectOutputStream(out);
			objOut.writeObject(obj);
			objOut.flush();
			objOut.close();
			System.out.println("write object success!");
		} catch (IOException e) {
			System.out.println("write object failed");
			e.printStackTrace();
		}
	}

	/**
	 * @info 将一个序列化的对象从文件中读取
	 * @param obj
	 */
	public static Object readObjectFromFile(String fileName) {
		Object temp = null;
		File file = new File(fileName);
		FileInputStream in;
		try {
			in = new FileInputStream(file);
			ObjectInputStream objIn = new ObjectInputStream(in);
			temp = objIn.readObject();
			objIn.close();
			System.out.println("read object success!");
		} catch (IOException e) {
			System.out.println("read object failed");
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return temp;
	}

	/**
	 * judge a string is or not a number.return boolean value
	 */
	public static boolean judgeStrIsNum(String s) {
		boolean is = false;
		char c[] = new char[s.length()];
		for (int i = 0; i < s.length(); i++) {
			c[i] = s.charAt(i);
		}
		for (int i = 0; i < c.length; i++) {
			if ((int) c[i] >= 48 && (int) c[i] <= 57) {
				is = true;
			} else {
				// 发现一个不是,直接结束
				return false;
			}
		}
		return is;
	}

	/**
	 * random birth no reExist number 0~9. you must input how many you want.
	 * This give a INT array for you.
	 */
	public static int[] birthNum(int n) {// 传入的参数是要生成的数字位数
		int[] num = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };// 从这个数组中随机取出<=9个数字
		int[] keep = new int[10];// 创建一个整数数组保存随机数字

		for (int i = num.length - 1; i >= 0; i--) {
			int k = (int) (Math.random() * i);// 生成的k值0～8
			keep[i] = num[k];// 取得数组前面的 10－i 个的其中一个值
			num[k] = num[i];// 将生成不到的数组值替换已经生成的数组值
			num[i] = keep[i];// 已经生成的放入再也生成不到的地方
		}
		int[] nn = new int[n];// 创建一个输入参数大小的数组
		nn = Arrays.copyOf(keep, n);// 取得随机数组的 需要的n个元素
		return nn;// 返回这个需要的数组
	}

	/**
	 * random birth no reExist number 0~9. you must input how many you want.
	 * This give a string for you.
	 */
	public static String birthNumString(int n) {// n传入的参数是要生成的数字位数
		int[] num = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };// 从这个数组中随机取出<=9个数字
		int[] keep = new int[10];// 创建一个整数数组保存随机数字

		for (int i = num.length - 1; i >= 0; i--) {
			int k = (int) (Math.random() * i);// 生成的k值0～8
			keep[i] = num[k];// 取得数组前面的 10－i 个的其中一个值
			num[k] = num[i];// 将生成不到的数组值替换已经生成的数组值
			num[i] = keep[i];// 已经生成的放入再也生成不到的地方
		}
		int[] nn = new int[n];// 创建一个输入参数大小的数组
		nn = Arrays.copyOf(keep, n);// 取得随机数组的 需要的n个元素
		String str = "";
		for (int i = 0; i < nn.length; i++) {
			str += nn[i];
		}
		return str;
	}

	// 取得唯一的字符串
	public static String getOneKeyS() {
		char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
		String str = "";
		chars = noSort(chars);// 无序
		for (int j = 0; j < chars.length; j++) {
			str += chars[j];
		}
		String timestr = System.currentTimeMillis() + "";
		String tmp = "";
		for (int i = 0; i < 4; i++) {
			tmp += str.substring(i * 3, i * 3 + 3) + timestr.substring(i * 3, i * 3 + 3);
		}
		tmp += timestr.substring(4 * 3, timestr.length()) + (int) (Math.random() * 1000);
		return tmp;
	}

	// 取得唯一的数字
	public static long getOnyKey() {
		char[] cs = ((long) (Math.random() * Long.MAX_VALUE) + "670123456789012345678967").toCharArray();
		cs = Atools.noSort(cs);
		String key = cs[1] + "" + System.currentTimeMillis() + cs[0] + "";
		return Long.parseLong(key);
	}

	// 字符数组无序排列
	public static char[] noSort(char[] obj) {
		char obj1[] = new char[obj.length];
		for (int i = obj.length - 1; i >= 0; i--) {
			int k = (int) (Math.random() * i);// 生成的k值
			obj1[i] = obj[k];// 取得数组前面的 10－i 个的其中一个值
			obj[k] = obj[i];// 将生成不到的数组值替换已经生成的数组值
			obj[i] = obj1[i];// 已经生成的放入再也生成不到的地方
		}
		return obj1;
	}

	// 字符数组无序排列
	public static int[] noSort(int[] obj) {
		int obj1[] = new int[obj.length];
		for (int i = obj.length - 1; i >= 0; i--) {
			int k = (int) (Math.random() * i);// 生成的k值0～8
			obj1[i] = obj[k];// 取得数组前面的 10－i 个的其中一个值
			obj[k] = obj[i];// 将生成不到的数组值替换已经生成的数组值
			obj[i] = obj1[i];// 已经生成的放入再也生成不到的地方
		}
		return obj1;
	}

	// 判断是否是素数
	// judge a number is or not primeNum
	public static boolean isPrime(int num) {
		if (num % 2 == 0)
			return false;
		else {
			int tmp = (int) Math.sqrt(num);
			for (int i = 3; i <= tmp; i++) {
				if (num % i == 0)
					return false;
			}
			return true;
		}
	}

	/**
	 * 打乱数组的顺序
	 * 
	 * @1 no sort array
	 * 
	 * @param obj
	 *            []
	 * @return obj[]
	 */
	public static Object[] noSort(Object[] obj) {
		Object obj1[] = new Object[obj.length];
		for (int i = obj.length - 1; i >= 0; i--) {
			int k = (int) (Math.random() * i);// 生成的k值0～8
			obj1[i] = obj[k];// 取得数组前面的 10－i 个的其中一个值
			obj[k] = obj[i];// 将生成不到的数组值替换已经生成的数组值
			obj[i] = obj1[i];// 已经生成的放入再也生成不到的地方
		}
		return obj1;
	}

	/**
	 * 随机从INT数组中抽出不重复的元素，转化为字符串<br>
	 * 输入生成字串的位数和INT数组
	 */
	public static String getXAttrFromArray(int x, int[] m) {
		int n[] = new int[m.length];
		for (int i = m.length - 1; i >= 0; i--) {
			int k = (int) (Math.random() * i);// 生成的k值0～8
			n[i] = m[k];// 取得数组前面的 10－i 个的其中一个值
			m[k] = m[i];// 将生成不到的数组值替换已经生成的数组值
			m[i] = n[i];// 已经生成的放入再也生成不到的地方
		}
		String s = "";
		for (int i = 0; i < x; i++) {
			s = s + n[i];
		}
		return s;
	}

	// 随机抽取数组m中的X个元素
	public static int[] getXIntFromArray(int x, int[] m) {
		int n[] = new int[m.length];
		for (int i = m.length - 1; i >= 0; i--) {
			int k = (int) (Math.random() * i);// 生成的k值0～8
			n[i] = m[k];// 取得数组前面的 10－i 个的其中一个值
			m[k] = m[i];// 将生成不到的数组值替换已经生成的数组值
			m[i] = n[i];// 已经生成的放在生成不到的位置
		}
		n = Arrays.copyOf(n, x);
		return n;
	}

	// 生成n个网络验证码
	public static String birthWebCode(int n) {
		String s = "";
		String st = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
		char[] str = st.toCharArray();
		for (int i = str.length - 1; i >= str.length - n; i--) {
			int k = (int) (Math.random() * i);
			char t = str[k];// 将随机生成的拿出来
			str[k] = str[i];// 将生成不到的放入可能生成的地方
			str[i] = t;
			s += t;
		}
		return s;
	}

	/**
	 * this is exchange two int array value
	 */
	public static void swapIntArray(int[] a, int b[]) {
		int a1 = a.length;
		int b1 = b.length;
		if (a1 > b1) {
			int[] tmp = new int[a1];
			for (int i = 0; i < tmp.length; i++) {
				tmp[i] = a[i];
			}
			a = new int[b1];
			for (int i = 0; i < a.length; i++) {
				a[i] = b[i];
			}
			b = new int[a1];
			for (int i = 0; i < tmp.length; i++) {
				b[i] = tmp[i];
			}
		} else {
			int[] tmp = new int[b1];
			for (int i = 0; i < tmp.length; i++) {
				tmp[i] = b[i];
			}
			b = new int[a1];
			for (int i = 0; i < b.length; i++) {
				b[i] = a[i];
			}
			a = new int[b1];
			for (int i = 0; i < tmp.length; i++) {
				a[i] = tmp[i];
			}

		}
	}

	/**
	 * 递归1~N的和
	 * 
	 * @param n
	 * @return
	 */
	public static int plus1toN(int n) {
		int res = 0;
		for (int i = 1; i <= n; i++) {
			res += i;
		}
		return res;
	}

	/**
	 * 递归1~N的积
	 * 
	 * @param n
	 * @return
	 */
	public static int ride1toN(int n) {
		int res = 0;
		for (int i = 1; i <= n; i++) {
			res *= i;
		}
		return res;
	}

	/**
	 * keep any float number. you input the double number d and keep count n<br>
	 * 保留N位小数
	 */
	public static double keepNround(double d, int n) {
		return Math.round(d * Math.pow(10, n)) / Math.pow(10, n);
	}

	/**
	 * @1 like a reSpeak word. 拼接N个字符串
	 */
	public static String nianJing(String str, Object... obj) {
		for (int i = 0; i < obj.length; i++) {
			str += obj;
		}
		return str;
	}

	/**
	 * 生成一个条码的最后一位数字,用于检验条形码
	 * 
	 * @param code12
	 * @return
	 */
	public static String birthLastCode12(String code12) {
		int m1 = 0, m2 = 0;
		for (int i = 0; i < code12.length() - 1; i += 2) {
			// i = 0 2 4 6 8 10
			char c = code12.charAt(i);// 取奇数位置的值
			int n = c - '0';
			m1 += n;// 算和
			m2 += code12.charAt(i + 1) - '0';// 算和
		}
		int mm = m1 + m2 * 3;
		int check = (10 - mm % 10) % 10;
		return code12 + check;
	}

	/** 验证邮箱 */
	public static boolean checkEmail(String str) {
		String res = "^(\\w-*\\.*)+@(\\w-?)+(\\.\\w{2,3})+";
		if (str.matches(res)) {
			return true;
		}
		return false;
	}

	/** 验证手机 */
	public static boolean checkMobile(String str) {
		String res = "^1[3,5,7,8]\\d{9}$";
		if (str.matches(res)) {
			return true;
		}
		return false;
	}

	/** 验证电话 */
	public static boolean checkPhone(String str) {
		String res = "^0\\d{2,3}-?\\d{7,8}$";
		if (str.matches(res)) {
			return true;
		}
		return false;
	}

	/** 验证用户名 */
	public static boolean checkUser(String str) {
		String res = "^[a-zA-z]\\w{3,15}$";
		if (str.matches(res)) {
			return true;
		}
		return false;
	}

	/** check the 条形码 is or not right */
	public static boolean checkCode13(String code13) {
		int m1 = 0, m2 = 0;
		for (int i = 0; i < code13.length() - 1; i += 2) {
			// i = 0 2 4 6 8 10
			char c = code13.charAt(i);// 取奇数位置的值
			int n = c - '0';
			m1 += n;// 算和
			m2 += code13.charAt(i + 1) - '0';// 算和
		}
		int mm = m1 + m2 * 3;
		int check = (10 - mm % 10) % 10;
		return check == code13.charAt(code13.length() - 1) - '0';
	}

	/**
	 * @info 判断是否相等
	 * @param l1
	 * @param l2
	 * @return
	 */
	public static boolean chkNumTypeEqual(Long l1, Long l2) {
		return l1.equals(l2) || l1 == l2;
	}

	/**
	 * 统计字符串中有多少这个字符<br>
	 * count this String has many this char
	 * 
	 * @param key
	 * @param s
	 * @return
	 */
	public static int[] judgeStringHas(char key, String s) {
		int[] ary = {};// null pk {},空杯子
		for (int i = 0; i < s.length(); i++) {
			char c = s.charAt(i);
			if (c == key) {
				ary = Arrays.copyOf(ary, ary.length + 1);// 扩展数组
				ary[ary.length - 1] = i;// 数组赋值
			}
		}
		return ary;
	}

	/**
	 * 统计字符串中有多少这个字符显示其位置<br>
	 * count this String has many this char
	 * 
	 * @param key
	 * @param s
	 * @return
	 */
	public static int[] judgeStringHas(String key, String s) {
		int[] ary = {};// null pk {},空杯子
		for (int i = 0; i < s.length(); i++) {
			char c = s.charAt(i);
			if (c == key.charAt(0)) {
				ary = Arrays.copyOf(ary, ary.length + 1);// 扩展数组
				ary[ary.length - 1] = i;// 数组赋值
			}
		}
		return ary;
	}

	/**
	 * 
	 * @param obj
	 * @return
	 */
	public static String echoArray(int[] obj) {
		String s = "";
		for (int i = 0; i < obj.length; i++) {
			s += obj[i] + ",";
		}
		return s.substring(0, s.length() - 1);
	}

	/* 全排列的结果 */
	public static long fun(long i) {
		long sum = 1;
		if (i <= 0 || i == 1)
			return sum;
		else
			return fun(i - 1) * i;
	}

	/** a个中取出b个排列 */
	public static long fun(long a, long b) {
		long sum = 0;
		if (b > a || a <= 0)
			return sum;
		else
			return fun(a) / fun(a - b);
	}

	/** a个中取出b个组合 */
	public static long fun_(long a, long b) {
		long sum = 0;
		if (b > a || a <= 0)
			return sum;
		else
			return fun(a) / fun(a - b) / fun(b);
	}

	public static BigDecimal fun(BigDecimal bd) {
		BigDecimal sum = new BigDecimal(1);
		if (bd.longValue() <= 1)
			return sum;
		else
			return bd.multiply(fun(bd.subtract(new BigDecimal(1))));
	}

	// 选择排序------标准java-selectSort算法---一行不多不少
	/**
	 * @0,思想就是每一次选择最小的放在前面,然后在剩下的继续选择 @1,[2|6,1,5,7] @2,[1,6|2,5,7]
	 *                                1 @3,[1,2,6|5,7] 2 @4,[1,2,5,6|7]
	 *                                3 @5,[1,2,5,6,7] 4 @6,
	 *                                i就是将第i个元素拿出来与后面的元素依次比较,把最小的选出来,放在第i个位置.
	 *                                同时比较的次数就是length-1;也用i控制 @7,
	 *                                j辅助第i个元素与后面的元素比较,所以j=i+1
	 */
	public static void classicsChoiceSort(int[] array) {
		for (int i = 0; i < array.length - 1; i++) {// 将未选的元素放在剩下的位置,最多1与length-1个比较
			for (int j = i + 1; j < array.length; j++) {// 每一次选择剩下的位置的最小的元素
				if (array[i] > array[j]) {
					int tmp = array[i];
					array[i] = array[j];
					array[j] = tmp;
				}
			}
		}
	}

	// 插入排序------标准java-insertSort算法---一行不多不少
	/**
	 * @1,[2,6,1,5,7] @2,[2j,6*i,1,5,7] 1 @3,[1-j,2-j,6*i,5,7] 2 @4,[1,2,5,6,7]
	 * 3 @5,[1,2,5,6,7] 4 @6,
	 */
	// 把1－length-1位置的元素，按照循环依次拿出来与前面的比较
	// i=<1-length-1> j=<i-1,0> j+1=i,i-1=j
	// 先把i位置的值拿出来,与前面的比较，小了，前面的后移，与更前面的比较，最后插入到没有更小的前面
	// 如果不小，就是大了，就不会出现移动，j--，就不用移动，所以，i位置的元素，还是回到i位置，ary[j+1]=t
	public static void classicsInsertSort(int[] array) {
		int i, j, t;
		for (i = 1; i < array.length; i++) {
			t = array[i];// i位置的在外面，准备插入
			for (j = i - 1; j >= 0 && t < array[j]; j--) {
				array[j + 1] = array[j];// 满足条件，就后移动，不会超过i位置
			}
			array[j + 1] = t;
		}
	}

	/** count year attribute */
	// 计算年份的属性
	public static String countYearAttribute(int year) {
		String str = "";
		int temp = (year + 57) % 60;
		int i = 1, j = 1, k = 1;
		String s1 = null, s2 = null, s3 = null;
		if (temp == 0) {
			str = "葵亥猪年";
		} else {
			for (k = 1; k <= temp; k++) {
				if (i <= 10) {
					i++;
				} else {
					i = 1;
					i++;
				}
				if (j <= 12) {
					j++;
				} else {
					j = 1;
					j++;
				}

			}
			switch (i - 1) {
			case 1:
				s1 = "甲";
				break;
			case 2:
				s1 = "乙";
				break;
			case 3:
				s1 = "丙";
				break;
			case 4:
				s1 = "丁";
				break;
			case 5:
				s1 = "戊";
				break;
			case 6:
				s1 = "己";
				break;
			case 7:
				s1 = "庚";
				break;
			case 8:
				s1 = "辛";
				break;
			case 9:
				s1 = "壬";
				break;
			case 10:
				s1 = "葵";
				break;

			}
			switch (j - 1) {
			case 1:
				s2 = "子";
				s3 = "鼠";
				break;
			case 2:
				s2 = "丑";
				s3 = "牛";
				break;
			case 3:
				s2 = "寅";
				s3 = "虎";
				break;
			case 4:
				s2 = "卯";
				s3 = "兔";
				break;
			case 5:
				s2 = "辰";
				s3 = "龙";
				break;
			case 6:
				s2 = "巳";
				s3 = "蛇";
				break;
			case 7:
				s2 = "午";
				s3 = "马";
				break;
			case 8:
				s2 = "未";
				s3 = "羊";
				break;
			case 9:
				s2 = "申";
				s3 = "猴";
				break;
			case 10:
				s2 = "尤";
				s3 = "鸡";
				break;
			case 11:
				s2 = "戌";
				s3 = "狗";
				break;
			case 12:
				s2 = "亥";
				s3 = "猪";
				break;
			}
			str = s1 + s2 + s3 + "年";
		}
		return str;
	}

	/** count now is hour and minute */
	// 计算几时几刻
	public static String countTimeMoment(int hour, int minute) {
		String s = "";
		if (hour >= 23 || hour < 1) {
			s = "子";
		}
		if (hour >= 1 && hour < 3) {
			s = "丑";
		}
		if (hour >= 3 && hour < 5) {
			s = "寅";
		}
		if (hour >= 5 && hour < 7) {
			s = "卯";
		}
		if (hour >= 7 && hour < 9) {
			s = "辰";
		}
		if (hour >= 9 && hour < 11) {
			s = "巳";
		}
		if (hour >= 11 && hour < 13) {
			s = "午";
		}
		if (hour >= 13 && hour < 15) {
			s = "未";
		}
		if (hour >= 15 && hour < 17) {
			s = "申";
		}
		if (hour >= 17 && hour < 19) {
			s = "尤";
		}
		if (hour >= 19 && hour < 21) {
			s = "戌";
		}
		if (hour >= 21 && hour < 23) {
			s = "亥";
		}
		if (hour % 2 == 0) {
			minute += 60;
		}
		int ke = minute / 15;
		if (ke == 0)
			s = s + "时";
		else
			s = s + "时" + ke + "刻";
		return s;
	}

	/** birth 54 cards */
	// 生成一副扑克牌54张 ，老方法
	public static String[] initCards() {
		String[] cards = new String[54];
		for (int i = 0; i < cards.length - 2; i++) {
			if (i % 4 == 0) {
				cards[i] = "红桃" + (i % 13 + 1);
			}
			if (i % 4 == 1) {
				cards[i] = "黑桃" + (i % 13 + 1);
			}
			if (i % 4 == 2) {
				cards[i] = "梅花" + (i % 13 + 1);
			}
			if (i % 4 == 3) {
				cards[i] = "方块" + (i % 13 + 1);
			}
		}
		cards[cards.length - 2] = "小王";
		cards[cards.length - 1] = "大王";
		return cards;
	}

	/** random check n cards */
	// 随机抽取n张牌,n<=54
	public static String[] choiceNCards(int n) {
		if (n <= 54) {
			String[] cards = initCards();
			boolean[] used = new boolean[cards.length];
			String[] nCards = new String[n];
			int i = 0;
			while (i < n) {
				Random r = new Random();
				int index = r.nextInt(cards.length);
				if (used[index]) {
					continue;
				}
				nCards[i++] = cards[index];
			}
			return nCards;
		} else
			return choiceNCards(54);
	}

	/** judge array is or not equals ,the arrays must overwrite hashCode */
	// 判断数组是否相等,如果是引用类型,需要hashCode(),equals()
	static boolean judgeArrayEquals(int[] ary1, int[] ary2) {
		if (ary1.length != ary2.length)
			return false;
		else {
			for (int i = 0; i < ary1.length; i++) {
				if (ary1[i] != ary2[i]) {
					return false;
				}
			}
			return true;
		}
	}

	/** make a string by a char and left align with length */
	public static String leftPad(String s, int length, char c) {
		int len = s.length();
		String tmp = "";
		for (int i = len; i < length; i++) {
			tmp += c;
		}
		s = tmp + s;
		return s;
	}

	/** make a string by a char and right align with length */
	// 将一个字串.按照指定的长度.以指定的字符右边对齐
	public static String rightPad(String s, int length, String string) {
		int len = s.length();
		String tmp = "";
		for (int i = len; i < length; i++) {
			tmp += string;
		}
		s = s + tmp;
		return s;
	}

	/** make a string repeat n times */
	// 将一个字串复制n遍
	public static String repeat(String s, int n) {
		String tmp = "";
		for (int i = 0; i < n; i++) {
			tmp += s;
		}
		return tmp;
	}

	/** AT object array's element insert a string */
	// 在Object对象的数组中的每一个元素之间插入一个字符串
	public static String join(Object[] obj, String s) {
		String tmp = "";
		for (int i = 0; i < obj.length - 1; i++) {
			tmp += obj[i] + s;
		}
		return tmp + obj[obj.length - 1];
	}

	/** This is a method for get the system time */
	// 获得当前的时间 2012-2-2 11:9:7
	public static String getFullTime() {
		String s = "";
		Date d1 = new Date();
		DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.CHINA);
		s = df.format(d1);
		Calendar c = Calendar.getInstance(Locale.CHINESE);
		s = s + " " + c.get(Calendar.HOUR_OF_DAY);
		s = s + ":" + c.get(Calendar.MINUTE);
		s = s + ":" + c.get(Calendar.SECOND);
		return s;
	}

	// 获得当前的时间 2012-2-2
	public static String getDate() {
		String s = "";
		Date d1 = new Date();
		DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.CHINA);
		s = df.format(d1);
		return s;
	}

	/**
	 * @info 时间格式化为相应格式的字符串
	 * @param d
	 * @param fmt
	 * @return
	 */
	public static String getStrFmtTime(Date d, String fmt) {
		SimpleDateFormat sdf = new SimpleDateFormat(fmt);
		return sdf.format(d);
	}

	public static String getStrFmtTime(String fmt) {
		SimpleDateFormat sdf = new SimpleDateFormat(fmt);
		return sdf.format(new Date());
	}

	public static String getStrFmtTime(String fmt, Date date) {
		SimpleDateFormat sdf = new SimpleDateFormat(fmt);
		return sdf.format(date);
	}

	/**
	 * @info 字符串转化为对应的时间
	 * @param d
	 * @param fmt
	 * @return
	 */
	public static Date getDateFmtStr(String dateStr, String fmt) {
		SimpleDateFormat sdf = new SimpleDateFormat(fmt);
		try {
			return sdf.parse(dateStr);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return new Date();
	}

	//

	// 获得当前的时间 11:9:7
	public static String getNowTime() {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
		return sdf.format(new Date());
	}

	public static String getFmtTime(String fmt) {
		SimpleDateFormat sdf = new SimpleDateFormat(fmt);
		return sdf.format(new Date());
	}

	// 获得年
	public static int getYear() {
		Calendar c = Calendar.getInstance();
		return c.get(Calendar.YEAR);

	}

	/**
	 * @info 字符在字符串中出现的次数
	 * @param string,s
	 * @return int
	 */
	public static int getCountChar(String string, String a) {
		int pos = -2;
		int n = 0;
		while (pos != -1) {
			if (pos == -2) {
				pos = -1;
			}
			pos = string.indexOf(a, pos + 1);
			if (pos != -1) {
				n++;
			}
		}
		return n;
	}

	/**
	 * @info 从字符串中匹配手机号码
	 * @param sParam
	 * @return
	 */
	public static String getPhoneNum(String sParam) {
		if (sParam.length() <= 0)
			return "";
		Pattern pattern = Pattern.compile("(1|861)(3|5|7|8)\\d{9}$*");
		Matcher matcher = pattern.matcher(sParam);
		StringBuffer bf = new StringBuffer();
		while (matcher.find()) {
			bf.append(matcher.group()).append(",");
		}
		int len = bf.length();
		if (len > 0) {
			bf.deleteCharAt(len - 1);
		}
		return bf.toString();
	}

	/**
	 * @info 从字符串中匹配身份证号码
	 * @param sParam
	 * @return
	 */
	public static String getIdcard(String sParam) {
		if (sParam.length() <= 0)
			return "";
		Pattern pattern = Pattern.compile("(\\d{17}[0-9Xx])");
		Matcher matcher = pattern.matcher(sParam);
		StringBuffer bf = new StringBuffer();
		while (matcher.find()) {
			bf.append(matcher.group()).append(",");
		}
		int len = bf.length();
		if (len > 0) {
			bf.deleteCharAt(len - 1);
		}
		return bf.toString();
	}

	/** This method is get a person's birthday */
	// 截取身份证的生日号码
	public static String getBirthdayFromIdCard(String idCard) {
		String s = idCard.substring(6, 14);
		return s;
	}

	/** depend on your person card count your ages */
	// 根据身份证号码算出岁数
	public static int getAgeFromIdCard(String idCard) throws ParseException {
		String s = idCard.substring(6, 10);
		int year1 = Integer.parseInt(s);
		s = idCard.substring(10, 14);
		int md = Integer.parseInt(s);
		Calendar c = Calendar.getInstance();
		int year2 = c.get(Calendar.YEAR);
		s = c.get(Calendar.MONTH) + 1 + "" + c.get(Calendar.DATE);
		int md2 = Integer.parseInt(s);
		int age = md2 - md >= 0 ? (year2 - year1 + 1) : (year2 - year1);
		return age;
	}

	/**
	 * @info 邮箱取得用户名
	 * @param email
	 * @return
	 */
	public static String getNameFromEmail(String email) {
		String name = email.substring(0, email.indexOf("@"));
		return name;
	}

	/**
	 * @info 邮箱取类型
	 * @param email
	 * @return
	 */
	public static String getEmailTypeFromEmail(String email) {
		String type = email.substring(email.indexOf("@") + 1, email.indexOf("."));
		return type;
	}

	/**
	 * count which years and month and days you must sign you pack . input the
	 * time years sign and how many years you sign.<br>
	 * Input sign Date and how many years;
	 */
	// 签订合同时,需要在到期前一个月续签,如果到期前一月的那天是周末,则延至下周一
	public static String signContractDateTime(Date create, int years) {
		Calendar c = new GregorianCalendar();
		c.setTime(create);// 设置日期
		c.add(Calendar.YEAR, years);
		c.add(Calendar.MONTH, -1);
		if (c.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)
			c.add(Calendar.DAY_OF_WEEK, 1);
		if (c.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY)
			c.add(Calendar.DAY_OF_WEEK, 2);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		return sdf.format(c.getTime());
	}

	/**
	 * make string by string ruler to calendar and set it be time<br>
	 * 把给定的日期字符串按照指定格式转换成Calendar类,并设置为时间
	 */
	public static Calendar getCal(String strDate, String fmt) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat(fmt);
		Date date = sdf.parse(strDate);
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal;
	}

	// 动态口令
	/** this is a dynamic password birth in client and server */
	public static String DynicPasswd(String str) {
		int hash = str.hashCode();
		// hash = Math.abs(hash);//取绝对值
		hash = hash >>> 1;// 无符号右移位
		Calendar c = Calendar.getInstance(Locale.CHINA);
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH) + 1;
		int day = c.get(Calendar.DAY_OF_MONTH);
		int hour = c.get(Calendar.HOUR_OF_DAY);
		int minute = c.get(Calendar.MINUTE);
		long value1 = (hash + year + hour + minute / 2);
		long value2 = (hash + month + day + minute / 2);
		long value3 = minute / 2 + hash;
		String v1 = "" + value1 % 10 + (value2 * 2) % 10 + "";
		String v2 = "" + value2 % 10 + (value3 * 3) % 10 + "";
		String v3 = "" + value3 % 10 + (value1 * 7) % 10 + "";
		String v = "";
		if (minute / 2 % 6 == 0) {
			v = v1 + v2 + v3;
		}
		if (minute / 2 % 6 == 1) {
			v = v3 + v2 + v1;
		}
		if (minute / 2 % 6 == 2) {
			v = v2 + v3 + v1;
		}
		if (minute / 2 % 6 == 3) {
			v = v3 + v1 + v2;
		}
		if (minute / 2 % 6 == 4) {
			v = v1 + v3 + v2;
		}
		if (minute / 2 % 6 == 5) {
			v = v2 + v3 + v1;
		}
		return v;
	}

	/**
	 * 矩阵是m行n列的数集,所以矩阵必须完整<br>
	 * The Matrix is m rows n COLS array <br>
	 * 转置矩阵
	 */
	public static int[][] transferMatrix(int[][] matrix) {
		int x = matrix.length;
		int y = matrix[0].length;
		int ary2[][] = new int[y][x];
		for (int i = 0; i < matrix.length; i++) {
			for (int j = 0; j < matrix[i].length; j++) {
				ary2[j][x - 1 - i] = matrix[i][j];
			}
		}
		return ary2;
	}

	/**
	 * 矩阵是m行n列的数集,所以矩阵必须完整<br>
	 * The Matrix is m rows n COLS array <br>
	 * 转置矩阵
	 */
	public static Object[][] transferMatrix2(Object[][] matrix) {
		int x = matrix.length;
		int y = matrix[0].length;
		Object ary2[][] = new Object[y][x];
		for (int i = 0; i < matrix.length; i++) {
			for (int j = 0; j < matrix[i].length; j++) {
				ary2[j][x - 1 - i] = matrix[i][j];
			}
		}
		return ary2;
	}

	/**
	 * 矩阵是m行n列的数集,所以矩阵必须完整<br>
	 * The Matrix is m rows n COLS array <br>
	 * 转置矩阵
	 */
	public static Object[][] transferListMap2MatrixObj(List<Map<String, Object>> matrix) {
		/*
		 * a 1 2 b 2 3 c 3 6 d 6 9 ----------- a b c d 1 2 3 6 2 3 6 9
		 */

		// 取得统一的KEY
		List<String> keys = new ArrayList<String>();
		Map<String, Object> map = matrix.get(0);
		Set<Entry<String, Object>> sets = map.entrySet();
		Iterator<Entry<String, Object>> ite = sets.iterator();
		while (ite.hasNext()) {
			Entry<String, Object> entry = ite.next();
			String key = entry.getKey();
			keys.add(key);
		}
		// 所有key完毕
		// 取值
		Object[][] objs = new Object[keys.size()][matrix.size()];
		for (int k = 0; k < matrix.size(); k++) {
			Map<String, Object> m = matrix.get(k);
			for (int i = 0; i < keys.size(); i++) {
				objs[i][k] = m.get(keys.get(i));
			}

		}

		return objs;
	}

	/***
	 * @info 线性表矩阵转秩
	 * @param matrix
	 * @return
	 */
	public static List<Map<String, Object>> transferListMap(List<Map<String, Object>> matrix) {
		List<Map<String, Object>> lists = new ArrayList<Map<String, Object>>();
		Object[][] objs = transferListMap2MatrixObj(matrix);
		for (Object[] o : objs) {
			Map<String, Object> m = new HashMap<String, Object>();
			for (int i = 0; i < o.length; i++) {
				m.put("k" + i, o[i].toString());
			}
			lists.add(m);
		}
		return lists;
	}

	/**
	 * 矩阵是m行n列的数集,所以矩阵必须完整<br>
	 * The Matrix is m rows n COLS array <br>
	 * 转置矩阵
	 */
	public static Object[][] transferListMap2MatrixObj(List<Map<String, Object>> matrix, List<String> keys) {
		// 取值
		Object[][] objs = new Object[keys.size()][matrix.size()];
		for (int k = 0; k < matrix.size(); k++) {
			Map<String, Object> m = matrix.get(k);
			for (int i = 0; i < keys.size(); i++) {
				objs[i][k] = m.get(keys.get(i));
			}

		}
		return objs;
	}

	/***
	 * @info 线性表矩阵转秩
	 * @param matrix
	 * @return
	 */
	public static List<Map<String, Object>> transferListMap(List<Map<String, Object>> matrix, ArrayList<String> keys) {
		List<Map<String, Object>> lists = new ArrayList<Map<String, Object>>();
		Object[][] objs = transferListMap2MatrixObj(matrix, keys);
		for (Object[] o : objs) {
			Map<String, Object> m = new HashMap<String, Object>();
			for (int i = 0; i < o.length; i++) {
				m.put("k" + i, o[i].toString());
			}
			lists.add(m);
		}
		return lists;
	}

	/** 列出系统的所有字体 */
	// 列出系统的字体
	public static String[] listFont() {
		String[] a = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();// 列出系统的字体
		return a;
	}

	// 指定文件夹的图片列出来
	public static List<String> listImg(String path) {
		List<String> imglist = new ArrayList<String>();
		File file = new File(path);
		File[] f = file.listFiles(new FileFilter() {
			public boolean accept(File ff) {
				// System.out.println(ff.getName());
				if (ff.getName().matches("^\\s*\\w*\\s*.(png|jpg|gif)$")) {// ([.png]|[.jpg]|[.gif])
					return true;
				}
				return false;
			}
		});
		for (int i = 0; i < f.length; i++) {
			imglist.add(f[i].toString());
		}
		// System.out.println(imglist);
		return imglist;
	}

	/**
	 * 列出指定文件夹的图片
	 * 
	 * @return
	 */
	public static List<String> listImg() {
		String path = openBag();
		List<String> imglist = new ArrayList<String>();
		File file = new File(path);
		File[] f = file.listFiles(new FileFilter() {
			public boolean accept(File ff) {
				// System.out.println(ff.getName());
				if (ff.getName().matches("^\\s*\\w*\\s*\\.(png|jpg|gif)$")) {// ([.png]|[.jpg]|[.gif])
					return true;
				}
				return false;
			}
		});
		for (int i = 0; i < f.length; i++) {
			imglist.add(f[i].toString());
		}
		// System.out.println(imglist);
		return imglist;
	}

	// 指定文件夹的图片列出来
	public static List<String> listImage() {
		String path = openFile();
		List<String> imglist = new ArrayList<String>();
		File file = new File(path);
		String fpath = file.getParentFile().getAbsolutePath();
		// System.out.println(fpath);
		file = new File(fpath);
		File[] f = file.listFiles(new FileFilter() {
			public boolean accept(File ff) {
				// System.out.println(ff.getName());
				if (ff.getName().matches("^\\s*\\w*\\s*\\.(png|jpg|gif)$")) {// ([.png]|[.jpg]|[.gif])
					return true;
				}
				return false;
			}
		});
		for (int i = 0; i < f.length; i++) {
			imglist.add(f[i].toString());
		}
		// System.out.println(imglist);
		return imglist;
	}

	/**
	 * @info 递归列出文件夹里的文件路径
	 * @param String
	 * @return Set
	 */
	public static Set<String> listDirAllFiles(String path) {
		File file = new File(path);
		if (!file.exists()) {
			return null;
		}
		if (file.isFile()) {
			Set<String> tmp = new HashSet<String>();
			tmp.add(path);
			return tmp;
		}
		if (file.isDirectory()) {
			return listFilesSet(listFilesMap(path));
		}
		return null;
	}

	private static Map<String, Object> listFilesMap(String path) {
		Map<String, Object> map = new HashMap<String, Object>();
		File file = new File(path);
		File[] fs = file.listFiles();
		for (File f : fs) {
			if (f.isDirectory()) {
				map.put(f.getAbsolutePath(), listFilesMap(f.getAbsolutePath()));
			} else {
				map.put(f.getAbsolutePath(), f.getName());
			}

		}
		return map;
	}

	@SuppressWarnings("unchecked")
	private static Set<String> listFilesSet(Map<String, Object> map) {
		Set<String> lists = new HashSet<String>();
		Set<Entry<String, Object>> sets = map.entrySet();
		Iterator<Entry<String, Object>> ite = sets.iterator();
		while (ite.hasNext()) {
			Entry<String, Object> entry = ite.next();
			File file = new File(entry.getKey());
			if (file.isFile()) {
				lists.add(entry.getKey());
			}
			if (entry.getValue() instanceof Map) {
				Map<String, Object> tmp = (Map<String, Object>) entry.getValue();
				lists.addAll(listFilesSet(tmp));
			}
		}
		return lists;
	}

	/**
	 * @info 递归列出文件夹里的文件或文件夹路径
	 * @param path
	 * @return List
	 */
	public static List<String> listFilePath(String path) {
		List<String> lists = new ArrayList<String>();
		File file = new File(path);
		if (!file.exists())
			return null;
		if (file.isFile()) {
			List<String> tmp = new ArrayList<String>();
			tmp.add(path);
			return tmp;
		}
		if (file.isDirectory()) {
			File[] fs = file.listFiles();
			for (File f : fs) {
				lists.add(f.getAbsolutePath());
			}
			return lists;
		}
		return null;
	}

	// 窗体居中的方法
	public static void setCenter(Window w) {
		int x = Toolkit.getDefaultToolkit().getScreenSize().width;
		int y = Toolkit.getDefaultToolkit().getScreenSize().height;
		w.setLocation(x / 2 - w.getWidth() / 2, y / 2 - w.getHeight() / 2);
	}

	// 按钮找到文件
	public static String openFile() {
		String path = "";
		File file;
		JFileChooser jfc = new JFileChooser();
		jfc = new JFileChooser();
		jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
		int n = jfc.showOpenDialog(null);
		if (n == JFileChooser.APPROVE_OPTION) {
			file = jfc.getSelectedFile();
			path = file.getAbsolutePath();
		}
		return path;
	}

	// 按钮找到文件夹
	public static String openBag() {
		String path = "";
		File file;
		JFileChooser jfc = new JFileChooser();
		jfc = new JFileChooser();
		jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		int n = jfc.showOpenDialog(null);
		if (n == JFileChooser.APPROVE_OPTION) {
			file = jfc.getSelectedFile();
			path = file.getAbsolutePath();
		}
		// System.out.println(path+"/");
		return path + "/";
	}

	// 读取多图片,指定文件路径
	public static List<ImageIcon> listImageIco() {
		List<ImageIcon> list = new LinkedList<ImageIcon>();
		File file = new File(openFile());
		file = file.getParentFile();
		File[] f = file.listFiles(new FileFilter() {
			public boolean accept(File ff) {
				// System.out.println(ff.getName());
				if (ff.getName().matches("^\\s*\\w*\\s*\\.(png|jpg|gif)$")) {// ([.png]|[.jpg]|[.gif])
					return true;
				}
				return false;
			}
		});
		for (int i = 0; i < f.length; i++) {
			// System.out.println(f[i].getAbsolutePath());
			ImageIcon ico = new ImageIcon(f[i].getAbsolutePath());
			list.add(ico);
		}
		// System.out.println(list);
		return list;
	}

	public static boolean createFile(String fileName) {
		String ss[] = null;
		try {
			ss = fileName.split("/");
		} catch (PatternSyntaxException e) {
			ss = fileName.split("\\");
		}
		String dir = "";
		for (int i = 0; i < ss.length - 1; i++) {
			dir += ss[i] + File.separator;
		}
		File file = new File(dir);
		if (!file.exists()) {
			file.mkdirs();
		}
		file = new File(dir + ss[ss.length - 1]);
		if (!file.exists()) {
			try {
				return file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}
		}
		return false;
	}

	/**
	 * @info 递归删除文件夹
	 * @param filename
	 */
	public static boolean deleteDirAllFiles(String pathname) {
		File file = new File(pathname);
		if (!file.exists())
			return true;
		if (!file.canWrite())
			return false;
		while (file.exists()) {
			deleteDirAndFiles(pathname);
		}
		return true;
	}

	private static void deleteDirAndFiles(String pathname) {
		File file = new File(pathname);
		if (!file.delete() && file.isDirectory()) {
			File[] fs = file.listFiles();
			for (File f : fs) {

				if (f.isDirectory()) {
					deleteDirAndFiles(f.getAbsolutePath());
				} else {
					f.delete();
				}
			}
		}
	}

	/**
	 * 递归删除文件加下的某个文件
	 * 
	 * @param file
	 * @param filename
	 */
	public static void deleteFileByFileName(File file, String filename) {
		File[] fs = file.listFiles();
		for (File f : fs) {
			if (f.isDirectory()) {
				deleteFileByFileName(f, filename);
			} else {
				if (filename.equals(f.getName()))
					f.delete();
			}
		}
	}

	// 递归找到所有的这个文件夹下的这种文件
	public static String deleteFileByFileName1(File file, String filename) {
		File[] fs = file.listFiles();
		for (File f : fs) {
			if (f.isDirectory()) {
				deleteFileByFileName(f, filename);
			} else {
				if (filename.equals(f.getName())) {
					f.delete();
				}
			}
		}
		return "Delete all files";
	}

	public static int deleteFileByFileName(File file, String filename, int i) {
		File[] fs = file.listFiles();
		for (File f : fs) {
			if (f.isDirectory()) {
				i = deleteFileByFileName(f, filename, i);
			} else {
				if (filename.equals(f.getName())) {
					f.delete();
					i++;
				}
			}
		}
		return i;
	}

	public static int deleteFileByFileName(String dir, String filename) {
		int i = 0;
		File file = new File(dir);
		return deleteFileByFileName(file, filename, i);
	}

	/**
	 * 1,实现文件(文本,图像等)的复制<br>
	 * one,implements copy file method
	 */
	// InputStream,BufferedInputStream
	public static void copy(String filein, String fileout) {
		try {
			// 为字节输入流家一个缓冲流
			InputStream in = new BufferedInputStream(new FileInputStream(filein));
			// 为字节输出流家一个缓冲流
			OutputStream out = new BufferedOutputStream(new FileOutputStream(fileout));
			// 循环写入文件
			int b;
			while ((b = in.read()) != -1) {
				out.write(b);
			}
			// 关闭流
			in.close();
			out.flush();
			out.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException("1,文件复制" + e);
		}
	}

	/**
	 * 1,实现文件(文本,图像等)的复制,重载方法<br>
	 * one,implements copy file method
	 */
	// DataInputStream
	public static void copy(File filein, File fileout) {
		try {
			// 数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型
			DataInputStream dis = new DataInputStream(new FileInputStream(filein));
			DataOutputStream dos = new DataOutputStream(new FileOutputStream(fileout));
			// 定义一个数组来缓冲,每一次读写4kbyte
			byte[] buf = new byte[1024 * 4];
			// 循环 读取写入文件
			int i;
			while ((i = dis.read(buf)) != -1) {
				dos.write(buf, 0, i);// 挖一瓢,有多少写多少
			}
			// 流的关闭
			dis.close();
			dos.flush();
			dos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			System.out.println("1,文件不存在异常");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 实现流的复制
	 * 
	 * @param in
	 * @param out
	 */
	public static void copy(InputStream in, OutputStream out) {
		byte[] b = new byte[1024 * 4];
		int n = -1;
		try {
			while ((n = in.read(b)) != -1) {
				out.write(b, 0, n);
			}
			out.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 将输入流转化为字节数组
	 * 
	 * @param in
	 * @return
	 */
	public static byte[] changeIO(InputStream in) {
		byte[] buf = new byte[0];
		try {
			byte[] b = new byte[1024 * 4];
			int n = -1;
			while ((n = in.read(b)) != -1) {
				int tmp = buf.length;
				Arrays.copyOf(buf, tmp + n);
				System.arraycopy(b, 0, buf, tmp, buf.length);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return buf;
	}

	/**
	 * 1,实现文件(文本,图像等)的复制,重载方法<br>
	 * one,implements copy file method
	 */
	// DataInputStream
	public static void copy(File filein, String fileout) {
		try {
			// 数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型
			DataInputStream dis = new DataInputStream(new FileInputStream(filein));
			DataOutputStream dos = new DataOutputStream(new FileOutputStream(fileout));
			// 定义一个数组来缓冲,每一次读写4kbyte
			byte[] buf = new byte[1024 * 4];
			// 循环 读取写入文件
			int i;
			while ((i = dis.read(buf)) != -1) {
				dos.write(buf, 0, i);// 挖一瓢,有多少写多少
			}
			// 流的关闭
			dis.close();
			dos.flush();
			dos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 1,实现文件(文本,图像等)的复制,重载方法<br>
	 * one,implements copy file method
	 */
	// 这个复习运用RandomAccessFile,可以文件锁
	public static void copy(String filein, File fileout) {
		try {
			RandomAccessFile raf = new RandomAccessFile(filein, "rw");
			RandomAccessFile raf1 = new RandomAccessFile(fileout, "rw");
			byte[] buf = new byte[1024];
			int i;
			raf.seek(0);// 移动指针
			raf1.seek(0);
			while ((i = raf.read(buf)) != -1) {
				raf1.write(buf, 0, i);
			}
			raf.close();
			raf1.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 2,十六进制打印输出---file
	 */
	// FileInputStream
	public static void printByte(String file) {
		try {
			// 字节输入流
			InputStream in = new FileInputStream(file);
			byte[] i = new byte[1];
			int time = 1;// 控制换行
			while ((in.read(i)) != -1) {
				if (i[0] < 16) {
					System.out.print(" ");
				}
				System.out.print("0x" + Integer.toHexString(i[0]) + ",");
				System.out.print((time++ % 16 == 0) ? "\n" : "");
			}
			in.close();
			System.out.println("总共:" + (time - 1) / 1024.0 + "个字节");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 2,十六进制打印输出---file
	 */
	// InputStream,BufferedInputStream,DataInputStream
	public static void print(File file) {
		try {
			InputStream in = new FileInputStream(file);
			BufferedInputStream br = new BufferedInputStream(in);
			DataInputStream dis = new DataInputStream(br);
			int i;
			int time = 1;
			while ((i = dis.read()) != -1) {
				if (i < 16)
					System.out.print("0");
				System.out.print(Integer.toHexString(i) + " | ");
				System.out.print((time++ % 16 == 0) ? "\n" : "");
			}
			dis.close();
			br.close();
			in.close();
			System.out.println("SIZE:" + (time - 1) / 1024.0 + "KB");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 2,十六进制打印输出---byte[]
	 */
	public static void print(byte[] buf) {
		// buf = {01000001,00001111,11010110,11010000}
		int i = 1;
		for (int b : buf) {
			// b = 00000000 00000000 00000000 01000001
			// 0xff 00000000 00000000 00000000 11111111 mask
			// & ---------------------------------------
			// 00000000 00000000 00000000 01000001
			b &= 0xff;
			// b = b & 0xff;//掩码运算 其中 0xff 叫掩码(mask)
			if (b <= 0xf) {// 单位数补0
				System.out.print("0");
			}
			System.out.print(Integer.toHexString(b) + " | ");
			if (i++ % 16 == 0) {
				System.out.println();
			}
		}
		System.out.println("打印了" + (i - 1) + " 个字节 ");
	}

	/**
	 * 3.读取字符,打印文本
	 */
	// FileReader,InputStreamReader默认的字符编码
	public static void printf(String file) {
		try {
			InputStreamReader in = new FileReader(file);
			int n, time = 1;
			while ((n = in.read()) != -1) {
				char c = (char) n;// 返回的是char的16进制
				time++;
				System.out.print(c);
			}
			System.out.println("总共字数:" + time);
			in.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 3.读取字符,打印文本
	 */
	// FileInputStream字节读入,InputStreamReader过滤器,BufferedInputStream缓冲,指定字符编码读取
	public static void printf(File file, String encoding) {
		try {
			InputStreamReader in = new InputStreamReader(new BufferedInputStream(new FileInputStream(file)), encoding);// 加入了缓冲
			char[] ch = new char[1024 * 4];// 自定义缓冲
			int n, time = 1;
			while ((n = in.read(ch)) != -1) {
				time++;
				in.read(ch, 0, n);
				for (char c : ch) {
					System.out.print(c);
				}
			}
			System.out.println("总共字数:" + time);
			in.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 3.读取字符,打印文本
	 */
	// BufferedReader,读取打印文本
	public static void printf(File file) {
		DataInputStream dis;
		try {
			dis = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
			BufferedReader in = new BufferedReader(new InputStreamReader(dis));
			int i, time = 0;
			while ((i = in.read()) != -1) {
				System.out.print((char) i);
				time++;
			}
			// 下面的可以读取,但是不靠谱.
			// char c;
			// try {
			// while ((int)(c = dis.readChar()) != -1) {
			// System.out.print(c);
			// }
			// } catch (EOFException e) {
			// System.out.println("读取完毕了");
			// }
			System.out.println("总字数:" + time);
			dis.close();
			in.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * 3.按指定编码读取文本,返回一个字符集合.
	 */
	// 指定编码读文本,读的最小单位是字符,2byte.
	public static ArrayList<Character> readByEncoding(File file, String encoding) {
		// 将文本保存到集合中
		ArrayList<Character> list = new ArrayList<Character>();
		try {
			InputStreamReader isr = new InputStreamReader(new BufferedInputStream(new FileInputStream(file)),

			encoding);
			int i; /* time = 1 */
			while ((i = isr.read()) != -1) {
				list.add((char) i);
				// System.out.print((char) i + " " + i + " "
				// + Integer.toHexString(i));
				// System.out.println(time++ % 10 == 0 ? "\n" : " ");
			}
			isr.close();
			return list;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return list;
	}

	// //////////////////////
	/**
	 * 4,深层复制<br>
	 * ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化<br>
	 * ObjectOutputStream 和 ObjectInputStream 分别与<br>
	 * FileOutputStream 和FileInputStream <br>
	 * 一起使用时，可以为应用程序提供对对象图形的持久存储。<br>
	 * ObjectInputStream用于恢复那些以前序列化的对象。是一个反序列化的过程.<br>
	 * 其他用途包括使用套接字流在主机之间传递对象，或者用于编组和解组远程通信系统中的实参和形参。<br>
	 * ObjectInputStream 确保从流创建的图形中所有对象的类型与 Java 虚拟机中显示的类相匹配。<br>
	 * 使用标准机制按需加载类。<br>
	 * 只有支持 java.io.Serializable 或 java.io.Externalizable 接口的对象才能从流读取。
	 */
	// ByteArrayOutputStream,ObjectOutputStream深度复制,读一个对象,写一个对象.
	public static Object deepCopy(Object obj) {
		try {
			// 利用内存的转换数组字节进行序列化和反序列化
			ByteArrayOutputStream buf = new ByteArrayOutputStream();
			// 序列化
			ObjectOutputStream out = new ObjectOutputStream(buf);
			out.writeObject(obj);// 对象转换为对象流在内存中转化缓冲的输出流
			out.close();// 关闭
			byte[] data = buf.toByteArray();// 将对象在内存中的内部缓冲区字节转化为数组
			ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data));// 内存中的内部缓冲区字节数组字节读取
			Object copy = in.readObject();// 读取的对象流转换为对象,反序列化过程
			in.close();
			return copy;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	/**
	 * 5,系统编码
	 * 
	 */
	// 获取系统编码
	public static String getSysEncoding() {
		return System.getProperty("file.encoding");
	}

	/**
	 * 6,统计文本中某个字符出现的次数,输入文件名和指定编码,返回集合Map类型
	 */
	// 统计文本中某个字符出现的次数,输入文件名和指定编码,返回集合Map类型
	public static Map<Character, Integer> countAll(String file, String encoding)
			throws IOException, FileNotFoundException {
		InputStreamReader in = new InputStreamReader(new BufferedInputStream(new FileInputStream(file)), encoding);
		// 过滤字符
		Set<Character> chs = new HashSet<Character>();
		chs.add('\n');
		chs.add('\t');
		chs.add('\r');
		chs.add(' ');
		chs.add(',');
		chs.add('。');
		chs.add('!');
		chs.add('，');
		chs.add('-');
		Map<Character, Integer> map = new HashMap<Character, Integer>();
		//
		int ch;
		while ((ch = in.read()) != -1) {
			char key = (char) ch;
			if (chs.contains(key))
				continue;
			Integer value = map.get(key);
			map.put(key, value = value == null ? 1 : value + 1);
		}
		in.close();

		return map;
	}

	/**
	 * @info 计算文件的大小
	 * @param path
	 * @return
	 */
	public static Long getFileSize(String path) {
		File file = new File(path);
		if (file.exists())
			return file.length();
		else
			return 0L;
	}

	// 统计文本文字总数,过滤标点等
	public static int countChar(String file, String encoding) {
		int all = 0;
		Collection<Integer> values;
		try {
			// 调用上面的方法
			values = countAll(file, encoding).values();
			for (int n : values) {
				all += n;
			}
			return all;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return all;
	}

	public static int countNoRepeatWord(String file, String encoding) throws FileNotFoundException, IOException {
		// 排序输出
		List<Entry<Character, Integer>> list = new ArrayList<Map.Entry<Character, Integer>>(
				countAll(file, encoding).entrySet());
		Collections.sort(list, new Comparator<Entry<Character, Integer>>() {
			public int compare(Entry<Character, Integer> o1, Entry<Character, Integer> o2) {
				return o2.getValue() - o1.getValue();
			}
		});
		return list.size();
	}

	// 前十个最多字
	public static HashMap<Character, Integer> sortMostChar(String file, String encoding)
			throws FileNotFoundException, IOException {
		// 排序输出
		List<Entry<Character, Integer>> list = new ArrayList<Map.Entry<Character, Integer>>(
				countAll(file, encoding).entrySet());
		Collections.sort(list, new Comparator<Entry<Character, Integer>>() {
			public int compare(Entry<Character, Integer> o1, Entry<Character, Integer> o2) {
				return o2.getValue() - o1.getValue();
			}
		});
		HashMap<Character, Integer> hash = new HashMap<Character, Integer>();
		for (int i = 0; i < 10; i++) {
			Entry<Character, Integer> entry = list.get(i);
			char ch = entry.getKey();
			int times = entry.getValue();
			hash.put(ch, times);
		}
		return hash;
	}

	/**
	 * 
	 * @param list
	 *            输入一个类型的List
	 * @return List 中对应数字值的排列名次序列数组(最大排第一)
	 */
	public static Integer[] sortList(List<?> list) {
		int size = list.size();
		Integer[] ints = new Integer[size];
		Object[] tmp = list.toArray();
		Arrays.sort(tmp);
		for (int j = list.size() - 1; j > -1; j--) {
			for (int i = 0; i < tmp.length; i++) {
				if (list.get(j) == tmp[i]) {
					ints[j] = list.size() - i;
				}
			}
		}
		// 去重复排名
		for (int i = 0; i < ints.length; i++) {
			for (int j = i + 1; j < ints.length; j++) {
				if (ints[j] == ints[i]) {
					ints[j] = ints[j] + 1;
				}
			}
		}
		return ints;
	}

	/**
	 * 
	 * @param list
	 *            要排名的List
	 * @param desc
	 *            是否降序
	 * @return array 排名的数组
	 */
	public static Integer[] sortList(List<?> list, boolean desc) {
		int size = list.size();
		Integer[] ints = new Integer[size];
		Object[] tmp = list.toArray();
		Arrays.sort(tmp);
		for (int j = list.size() - 1; j > -1; j--) {
			for (int i = 0; i < tmp.length; i++) {
				if (list.get(j) == tmp[i]) {
					if (desc)
						ints[j] = list.size() - i;
					else
						ints[j] = i + 1;
				}
			}
		}
		// 去重复排名
		for (int i = 0; i < ints.length; i++) {
			for (int j = i + 1; j < ints.length; j++) {
				if (ints[j] == ints[i]) {
					if (desc)
						ints[j] = ints[j] + 1;
					else
						ints[j] = ints[j] - 1;
				}
			}
		}
		return ints;
	}

	/**
	 * 倒序线性表
	 * 
	 * @param lists
	 * @return
	 */

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static List oppositeSortList(List lists) {
		List ls = new ArrayList();
		for (int i = lists.size() - 1; i >= 0; i--) {
			ls.add(lists.get(i));
		}
		return ls;
	}

	/**
	 * 7,复制.<br>
	 * 对指定的文本,按照指定编码读取,写入到另一个文本,需要指定编码<br>
	 * 例如:gbk的书籍,转变成utf8的书籍,直接可以这样转变
	 * 
	 * @param file1
	 * @param encoding1
	 * @param file2
	 * @param encoding2
	 */
	// 读取指定的编码文本,写出到指定的编码文本
	public static void copy(String file1, String encoding1, String file2, String encoding2) {
		try {
			// 创建按照指定编码的输入流对象
			InputStreamReader isr = new InputStreamReader(new BufferedInputStream(new FileInputStream(file1)),
					encoding1);
			// 创建按照指定编码的输出流对象
			OutputStreamWriter osw = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(file2)),
					encoding2);// 带有缓冲
			char[] ch = new char[1024 * 8];
			int i;
			while ((i = isr.read(ch)) != -1) {
				osw.write(ch, 0, i);
			}
			osw.flush();
			isr.close();
			osw.close();
			System.out.println("复制完毕");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * 8,分割文件,输入文件名,单位分割的大小
	 * 
	 * @param file
	 *            文件名
	 * @param size
	 *            分割的单个文件大小 单位是:kb
	 */
	// 分割文件
	public static void spilt(String file, int size) {
		int idx = 0;
		if (size <= 0) {
			throw new IllegalArgumentException("文件大小不可以为负数");
		}
		try {
			// 1,构建输入输出流
			InputStream in = new BufferedInputStream(new FileInputStream(file));
			OutputStream out = new BufferedOutputStream(new FileOutputStream(file + "." + idx));
			// 2,读取文件并且切分
			int n;
			int count = 0;
			while ((n = in.read()) != -1) {
				out.write(n);
				count++;
				// 切分
				if (count % (size * 1024) == 0) {
					out.close();
					out = new BufferedOutputStream(new FileOutputStream(file + "." + (++idx)));
				}
			}
			in.close();
			out.close();
			System.out.println("分割成" + (++idx) + "个文件");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * 9,合并文件
	 */
	// 合并文件
	public static void join(String file) {
		// 1,获取合并文件的文件名
		String filename = file.substring(0, file.lastIndexOf("."));

		// 3,创建输出流 (输出到合并文件)
		try {
			OutputStream out = new BufferedOutputStream(new FileOutputStream(filename));
			// 4,创建输入流,循环写入到文件
			int idx = 0;
			File f = new File(file);
			while (f.exists()) {
				// 4.1构建输入流
				InputStream in = new BufferedInputStream(new FileInputStream(f));
				// 4.2由输出流循环写入合并文件
				int b;
				while ((b = in.read()) != -1) {
					out.write(b);
				}
				// 4.3关闭流
				out.flush();
				in.close();
				// 4.4构建新文件
				f = new File(filename + "." + ++idx);
			}
			out.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * 9,合并文件,第一个参数是合并后的文件名,后面的是要合并的文件列表 1,合并文件,输入要合并的文件的名字,从前到后,依次输入<br>
	 * 2,第一个参数是合并输出的文件名
	 */
	public static void join(String fileoutname, String... file) {
		// 1,创建合并输出的文件
		try {
			OutputStream out = new BufferedOutputStream(new FileOutputStream(fileoutname));
			// 2,将要合并的文件一次写入
			for (int i = 0; i < file.length; i++) {
				String string = file[i];
				// 2.1创建输入的流
				InputStream in = new BufferedInputStream(new FileInputStream(string));
				int b;
				while ((b = in.read()) != -1) {
					out.write(b);
				}
				out.flush();
				in.close();
			}
			// 关闭流
			out.close();
			System.out.println("合并完成");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	// 读取指定的编码文件,写出到指定的编码文件(文本,图片等等)

	/**
	 * 10, 指定字符串,按照指定的编码方式,写入指定的文本,是字符流
	 */
	// 指定字符串,按照指定的编码方式,写入指定的文本
	public static void writeS(String str, String encoding, String file) {
		char[] cuf = str.toCharArray();// 将指定的字串序列化为byte[]
		try {
			OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file), encoding);
			out.write(cuf);
			out.flush();
			out.close();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	public static void writeStrAppend(String fileName, String str) {
		try {
			File file = new File(fileName);
			if (!file.exists()) {
				file.createNewFile();
			}
			String outFile = System.currentTimeMillis() + ".txt";
			InputStream in = new FileInputStream(file);
			OutputStream out = new FileOutputStream(outFile);
			byte[] bs = new byte[1024];
			int i = -1;
			while ((i = in.read(bs)) != -1) {
				out.write(bs, 0, i);
			}
			in.close();
			out.flush();
			byte[] b = str.getBytes();
			out.write(b);
			out.flush();
			out.close();
			File f = new File(outFile);
			File fi = new File(fileName);
			fi.delete();
			f.renameTo(new File(fileName));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void writeStrNextLine(String fileName, String str) {
		try {
			String pathname = System.currentTimeMillis() + ".txt";
			File file = new File(fileName);
			if (!file.exists()) {
				file.createNewFile();
			}
			BufferedReader br = new BufferedReader(new FileReader(file));
			File temp = new File(pathname);
			BufferedWriter bw = new BufferedWriter(new FileWriter(temp));
			String s = null;
			while ((s = br.readLine()) != null) {
				bw.write(s);
				bw.newLine();
			}
			br.close();
			bw.flush();
			char[] chs = str.toCharArray();
			for (int j = 0; j < chs.length; j++) {
				if (chs[j] == '\n' || chs[j] == '\r')
					bw.newLine();
				bw.write(chs[j] + "");
			}
			bw.flush();
			bw.close();
			file.delete();
			temp.renameTo(file);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 11, 指定文件,按照指定编码读取,转化为字符串数组
	 */
	// 11从文本读取信息
	public static String[] readName(String file, String encoding) {
		String[] name = null;
		String str = null;
		try {
			InputStreamReader in = new InputStreamReader(new FileInputStream(file), encoding);
			char[] ch = new char[1024 * 4];
			int n;
			while ((n = in.read(ch)) != -1) {
				in.read(ch, 0, n);
			}
			for (int i = 0; i < n; i++) {
				if (ch[i] == '\t' || ch[i] == '\n' || ch[i] == '\r') {
					continue;
				} else {
					str += ch[i];
				}
			}
			str = new String(ch);
			name = str.trim().split(",");
			in.close();
			return name;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return name;
	}

	/**
	 * 
	 * @param path
	 *            路径
	 * @param w
	 *            每单个的宽
	 * @param h
	 *            每单个的高
	 * @return BufferedImage[][]
	 */
	public static BufferedImage[][] split(String path, int w, int h) {
		try {
			BufferedImage image = ImageIO.read(new File(path));
			int col = image.getWidth() / w;
			int row = image.getHeight() / h;
			BufferedImage[][] bi = new BufferedImage[row][col];
			for (int i = 0; i < row; i++) {
				for (int j = 0; j < col; j++) {
					bi[i][j] = image.getSubimage(j * w, i * h, w, h);
				}
			}
			return bi;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	public static void echoAll(int w, int h) throws Exception {
		String path = openFile();
		BufferedImage[][] bi = split(path, w, h);
		String path2 = openBag();
		for (int i = 0; i < bi.length; i++) {
			for (int j = 0; j < bi[0].length; j++) {
				ImageOutputStream out = ImageIO.createImageOutputStream(new FileOutputStream(path2 + j + ".gif"));
				boolean b = ImageIO.write(bi[i][j], "gif", out);
				System.out.println(i * j + " is " + b);
			}
		}
	}

	/** 网络的消息发送 */
	// 3,发送消息的方法,参数消息字串,指定套结字
	public static void sendMsg(String msg, Socket s) {
		try {
			BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
			out.write(msg);
			out.flush();
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/** 网络的文件发送 */
	// 4,发送文件的方法
	public static void sendFile(String file, Socket s) {
		// 文件的发送需要先读取
		try {
			InputStream in = new FileInputStream(file);
			OutputStream out = s.getOutputStream();
			byte[] buf = new byte[1024 * 8];
			int a;
			while ((a = in.read(buf)) != -1) {
				out.write(buf, 0, a);
			}
			out.flush();
			out.close();
			in.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/** 网络的消息接收 */
	// 5,消息的读取方法
	public static String readMsg(Socket s) {
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
			String str, string = "";
			while ((str = br.readLine()) != null) {
				string += str;
			}
			br.close();
			return string;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return "";
	}

	/** 网络的文件接收 */
	// 6,文件的读取方法,套接字读取,指定套接字和保存的文件路径
	public static void readFile(Socket s, String file) {
		try {
			OutputStream out = new FileOutputStream(file);
			InputStream in = s.getInputStream();
			byte[] buf = new byte[1024 * 4];
			int b;
			while ((b = in.read(buf)) != -1) {
				out.write(buf, 0, b);
			}
			out.flush();
			out.close();
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// 将字节数组转被化为图形
	public static ImageIcon displayImg(byte[] img) {
		// 利用内存的转换数组字节进行序列化和反序列化
		// ByteArrayInputStream buf = new ByteArrayInputStream(img);
		InputStream in = new ByteArrayInputStream(img);
		try {
			BufferedImage image = ImageIO.read(in);
			ImageIcon ico = new ImageIcon(img);// 1方法
			ico = new ImageIcon(image);// 2方法
			return ico;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 1<br>
	 * 根据类的名字创建类的对象 创建对象<br>
	 * 第一种, 便捷是使用默认构造器创建实例 <br>
	 * //反射API, 的入口都是从Class实例开始 <BR>
	 * //Class.forName()是静态方法, 去查找内存是否有className <br>
	 * //对应的类的实例, 如果没有就加载这个类, 从CLASSPATH上加载 <br>
	 * //如果CLASSPATH上没有找到类的定义抛出: ClassNotFoundException
	 * 
	 * @param classname
	 * @return obj
	 */
	public static Object create(String classname) {
		try {
			Class<?> cls = Class.forName(classname);
			Object obj = cls.newInstance();
			return obj;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 2<br>
	 * 创建某类型的实例(调用构造器,含有参数列表的构造器)
	 * 
	 * @param className
	 *            类名
	 * @param paramTypes
	 *            参数类型列表: 如: new Class[]{int.class, String.class} 表示: int,String
	 * @param params
	 *            参数列表 如: new Object[]{5, "50"} 表示: 5,"50"
	 */
	public static Object create(String classname, Class<?>[] paramTypes, Object[] params) {

		try {
			// 找到类型
			Class<?> cls = Class.forName(classname);
			// 找到构造器
			Constructor<?> c = cls.getConstructor(paramTypes);
			// 根据参数创建对象
			Object obj = c.newInstance(params);
			return obj;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 依据对象找到其信息
	 * 
	 * @param obj
	 * @return
	 */
	public static String discover(Object obj) {
		String s = "", s1 = "", s2 = "", s3 = "";
		Class<?> cls = obj.getClass();
		s += "ClassName:" + cls.getName();
		Field[] fields = cls.getDeclaredFields();
		for (Field field : fields) {
			s1 += "Attribute Type:" + field.getType() + ",Attribute Name:" + field.getName() + "\n";
		}
		// 发现类的方法
		Method[] methods = cls.getDeclaredMethods();
		for (Method method : methods) {
			s2 += "Return Type:" + method.getReturnType() + ",Method Name:" + method.getName() + ",Param List:"
					+ Arrays.toString(method.getTypeParameters()) + "\n";
		}
		// 发现类的构造器返回 Constructor 对象的一个数组，这些对象反映此 Class 对象表示的类声明的所有构造方法
		Constructor<?>[] c = cls.getDeclaredConstructors();
		for (Constructor<?> co : c) {
			s3 += "Constructor Name:" + co.getName() + ",Constructor Params List:"
					+ Arrays.toString(co.getParameterTypes()) + "\n";
		}

		return s + s1 + s2 + s3;
	}

	/**
	 * 4<br>
	 * 访问某对象的方法
	 * 
	 * @param obj
	 *            被调用方法的对象
	 * @param method
	 *            方法名
	 * @param paramTypes
	 *            方法参数类型列表
	 * @param params
	 *            方法参数列表
	 * @return 方法返回值
	 */
	public static Object call(Object obj, String methodname, Class<?>[] paramTypes, Object[] params) {
		// 1,获得类型
		Class<?> cls = obj.getClass();
		try {
			// 2,获得方法,根据类型,方法名,参数类型
			Method m = cls.getDeclaredMethod(methodname, paramTypes);
			// 3,使用invoke()调用方法,传入(obj, params),获得返回的值
			Object value = m.invoke(obj, params);
			return value;// 所有的返回数据都有类型
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 5<br>
	 * 访问某对象的属性
	 * 
	 * @param obj
	 *            某对象
	 * @param fieldName
	 *            某属性名
	 * @return 属性的值
	 */
	public static Object getFieldValue(Object obj, String fieldname) {
		try {
			// 1,根据对象获得类型
			Class<?> cls = obj.getClass();
			// 2,根据类型和属性名获得字段
			Field field = cls.getField(fieldname);
			// 3,字段的方法调用属性的值
			Object value = field.get(obj);
			// field.get(obj)返回指定对象上此Field表示的字段的值
			return value;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 将字符串转化为SQL的时间日期
	 * 
	 * @param s
	 * @return
	 */
	public static java.sql.Date str2SqlDate(String s) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		java.util.Date d = null;
		try {
			d = sdf.parse(s);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return new java.sql.Date(d.getTime());
	}

	/**
	 * 
	 * @param s
	 * @return
	 */
	public static java.sql.Time str2SqlTime(String s) {
		SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
		java.util.Date t = null;
		try {
			t = sdf.parse(s);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return new java.sql.Time(t.getTime());
	}

	/**
	 * 
	 * @param s
	 * @return
	 */
	public static java.sql.Timestamp str2SqlDateTime(String s) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		java.util.Date t = null;
		try {
			t = sdf.parse(s);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return new java.sql.Timestamp(t.getTime());
	}

	/**
	 * byte to int
	 */
	public static int bytes2Int(byte[] bytes) {
		int num = bytes[3] & 0xff;
		num |= ((bytes[2] << 8) & 0xff00);
		num |= ((bytes[1] << 16) & 0xff0000);
		num |= ((bytes[0] << 24) & 0xff000000);
		return num;
	}

	/**
	 * @info 取得星期几
	 * @param date
	 * @return
	 */
	public static String getWeekOfDate(Date date) {
		String[] weekOfDays = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
		Calendar calendar = Calendar.getInstance();
		if (date != null) {
			calendar.setTime(date);
		}
		int w = calendar.get(Calendar.DAY_OF_WEEK) - 1;
		if (w < 0) {
			w = 0;
		}
		return weekOfDays[w];
	}

	/**
	 * @info 取得周几的序号
	 * @param date
	 * @return
	 */
	public static int getWeekNum(Date date) {
		Calendar calendar = Calendar.getInstance();
		if (date != null) {
			calendar.setTime(date);
		}

		int w = calendar.get(Calendar.DAY_OF_WEEK) - 1;
		if (w < 0) {
			w = 0;
		}
		return w;
	}

	/**
	 * @info 对密码进行不可反转加密
	 * @param str
	 * @return
	 */
	public static String makePwd(String str) {
		String md5 = getMD5Code(str);
		char[] cs = dschg(daoxu(md5.toCharArray()));
		String sha = new String(cs);
		return sha;
	}

	/**
	 * @info 验证密码是否正确
	 * @param pwd1
	 * @param pwd2
	 * @return
	 */
	public static boolean checkPwd(String pwd1, String pwd2) {
		try {
			String p1 = Atools.makePwd(Atools.jsJieMi(pwd1));
			String p2 = Atools.jiemi(pwd2);
			if (p1.equals(p2)) {
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
			return false;
		}

	}

	/**
	 * jsjiami的解密
	 */
	public static String jsJieMi(String sha) throws Exception {
		char[] cs = sha.toCharArray();
		cs = dschg(cs);
		String pwd = new String(cs);
		pwd = decode64(pwd);
		return pwd;
	}

	/**
	 * @info AAT加密算法2
	 * @param pwd
	 * @return
	 */
	public static String jiami(String pwd, String key8) {
		String str = birthNumString(6) + pwd + birthNumString(6);
		char[] cs = str.toCharArray();
		cs = daoxu(cs);
		cs = dschg(cs);
		String sha = "";
		try {
			sha = birthWebCode(3) + encrypt(new String(cs), key8) + birthWebCode(3);
		} catch (Exception e) {
		}
		return sha;
	}

	/**
	 * @info AAT解密算法2
	 * @param sha
	 * @return
	 * @throws Exception
	 */
	public static String jiemi(String sha, String key8) throws Exception {
		sha = sha.substring(3, sha.length() - 3);
		String str = decrypt(sha, key8);
		char[] cs = str.toCharArray();
		cs = dschg(cs);
		cs = daoxu(cs);
		String pwd = new String(cs);
		pwd = pwd.substring(6, pwd.length() - 6);
		return pwd;
	}

	/**
	 * @info AAT加密算法
	 * @param pwd
	 * @return
	 */
	public static String jiami(String pwd) {
		String str = birthNumString(6) + pwd + birthNumString(6);
		char[] cs = str.toCharArray();
		cs = daoxu(cs);
		cs = dschg(cs);
		String sha = birthWebCode(3) + encode64(new String(cs)) + birthWebCode(3);
		return sha;
	}

	/**
	 * @info AAT解密算法
	 * @param sha
	 * @return
	 * @throws Exception
	 */
	public static String jiemi(String sha) throws Exception {
		sha = sha.substring(3, sha.length() - 3);
		String str = decode64(sha);
		char[] cs = str.toCharArray();
		cs = dschg(cs);
		cs = daoxu(cs);
		String pwd = new String(cs);
		pwd = pwd.substring(6, pwd.length() - 6);
		return pwd;
	}

	// 解密数据
	private static String decrypt(String message, String key) throws Exception {

		byte[] bytesrc = convertHexString(message);
		Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
		DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
		IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8"));

		cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);

		byte[] retByte = cipher.doFinal(bytesrc);
		return new String(retByte);
	}

	// 加密
	private static String encrypt(String message, String key) throws Exception {
		String jiami = java.net.URLEncoder.encode(message, "utf-8").toLowerCase();
		String res = toHexString(encrypt1(jiami, key)).toUpperCase();
		return res;
	}

	private static byte[] encrypt1(String message, String key) throws Exception {
		Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

		DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));

		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
		IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8"));
		cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);

		return cipher.doFinal(message.getBytes("UTF-8"));
	}

	private static byte[] convertHexString(String ss) {
		byte digest[] = new byte[ss.length() / 2];
		for (int i = 0; i < digest.length; i++) {
			String byteString = ss.substring(2 * i, 2 * i + 2);
			int byteValue = Integer.parseInt(byteString, 16);
			digest[i] = (byte) byteValue;
		}

		return digest;
	}

	private static String toHexString(byte b[]) {
		StringBuffer hexString = new StringBuffer();
		for (int i = 0; i < b.length; i++) {
			String plainText = Integer.toHexString(0xff & b[i]);
			if (plainText.length() < 2)
				plainText = "0" + plainText;
			hexString.append(plainText);
		}

		return hexString.toString();
	}

	/**
	 * @info 倒序排序
	 * @param cs
	 * @return
	 */
	public static char[] daoxu(char[] cs) {
		int length = cs.length;
		char[] csp = new char[length];
		for (int i = 0; i < length; i++) {
			csp[i] = cs[length - 1 - i];
		}
		return csp;
	}

	/**
	 * @info 单双替换
	 * @param cs
	 * @return
	 */
	public static char[] dschg(char[] cs) {
		int length = cs.length;
		char[] csp = new char[length];
		for (int i = 0; i < length / 2; i++) {
			csp[2 * i] = cs[2 * i + 1];
			csp[2 * i + 1] = cs[2 * i];
		}
		if (length % 2 != 0) {
			csp[length - 1] = cs[length - 1];
		}
		return csp;
	}

	/**
	 * @info URL截取
	 * @param indexStr
	 * @param endStr
	 * @param url
	 * @return
	 * @demo http://pku.dizena.com/pku/20140103140/do.html?uri=加密URL&now=
	 *       加密datetime
	 */
	public static String urlGet(String indexStr, String endStr, String url) {
		int i1 = url.indexOf(indexStr);
		int i2 = url.indexOf(endStr);
		int i3 = i1 + indexStr.length();
		if (i1 != -1 && i2 != -1 && i1 > i2 && i3 <= i2)
			return url.substring(url.indexOf(indexStr) + indexStr.length(), url.indexOf(endStr));
		else
			return null;
	}

	// 全局数组
	private final static String[] strDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d",
			"e", "f" };

	// 返回形式为数字跟字符串
	private static String byteToArrayString(byte bByte) {
		int iRet = bByte;
		// System.out.println("iRet="+iRet);
		if (iRet < 0) {
			iRet += 256;
		}
		int iD1 = iRet / 16;
		int iD2 = iRet % 16;
		return strDigits[iD1] + strDigits[iD2];
	}

	// 转换字节数组为16进制字串
	private static String byteToString(byte[] bByte) {
		StringBuffer sBuffer = new StringBuffer();
		for (int i = 0; i < bByte.length; i++) {
			sBuffer.append(byteToArrayString(bByte[i]));
		}
		return sBuffer.toString();
	}

	public static String getMD5Code(String strObj) {
		String resultString = null;
		try {
			resultString = new String(strObj);
			MessageDigest md = MessageDigest.getInstance("MD5");
			// md.digest() 该函数返回值为存放哈希值结果的byte数组
			resultString = byteToString(md.digest(strObj.getBytes()));
		} catch (NoSuchAlgorithmException ex) {
			ex.printStackTrace();
		}
		return resultString;
	}

	private static byte[] base64DecodeChars = new byte[] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
			5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26,
			27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1,
			-1, -1, -1 };

	private static byte[] decode(String str) {
		byte[] data = str.getBytes();
		int len = data.length;
		ByteArrayOutputStream buf = new ByteArrayOutputStream(len);
		int i = 0;
		int b1, b2, b3, b4;

		while (i < len) {
			do {
				b1 = base64DecodeChars[data[i++]];
			} while (i < len && b1 == -1);
			if (b1 == -1) {
				break;
			}

			do {
				b2 = base64DecodeChars[data[i++]];
			} while (i < len && b2 == -1);
			if (b2 == -1) {
				break;
			}
			buf.write((int) ((b1 << 2) | ((b2 & 0x30) >>> 4)));

			do {
				b3 = data[i++];
				if (b3 == 61) {
					return buf.toByteArray();
				}
				b3 = base64DecodeChars[b3];
			} while (i < len && b3 == -1);
			if (b3 == -1) {
				break;
			}
			buf.write((int) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2)));

			do {
				b4 = data[i++];
				if (b4 == 61) {
					return buf.toByteArray();
				}
				b4 = base64DecodeChars[b4];
			} while (i < len && b4 == -1);
			if (b4 == -1) {
				break;
			}
			buf.write((int) (((b3 & 0x03) << 6) | b4));
		}
		return buf.toByteArray();
	}

	/**
	 * @info 解密
	 * @param 解密字符串
	 * @return
	 */
	public static String decode64(String str) {
		if (null == str)
			return "";
		return new String(decode(str));
	}

	/**
	 * @info 加密
	 * @param 加密字符串
	 * @return
	 */
	public static String encode64(String input) {
		String keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
		String output = "";
		int chr1 = 0, chr2 = 0, chr3 = 0;
		int enc1, enc2, enc3, enc4;
		int i = 0;
		while (i < input.length()) {
			chr1 = (int) input.toCharArray()[i++];
			enc1 = chr1 >> 2;
			if (i >= input.length()) {
				enc2 = ((chr1 & 3) << 4);
				enc3 = enc4 = 64;
			} else {
				chr2 = (int) input.toCharArray()[i++];
				enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
				if (i >= input.length()) {
					enc3 = ((chr2 & 15) << 2);
					enc4 = 64;
				} else {
					chr3 = (int) input.toCharArray()[i++];
					enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
					enc4 = chr3 & 63;
				}
			}

			output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);
			chr1 = chr2 = chr3 = 0;
			enc1 = enc2 = enc3 = enc4 = 0;
		}
		return output;
	}

	// 加密-原始的算法
	static String encode64a(String input) {
		String keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
		String output = "";
		int chr1 = 0, chr2 = 0, chr3 = 0;
		int enc1, enc2, enc3, enc4;
		int i = 0;
		while (i < input.length()) {
			chr1 = (int) input.toCharArray()[i++];
			try {
				chr2 = (int) input.toCharArray()[i++];
			} catch (Exception e) {
				enc3 = enc4 = 64;
			}
			try {
				chr3 = (int) input.toCharArray()[i++];
			} catch (Exception e) {
				enc4 = 64;
			}
			enc1 = chr1 >> 2;
			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
			enc4 = chr3 & 63;

			output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);
			chr1 = chr2 = chr3 = 0;
			enc1 = enc2 = enc3 = enc4 = 0;
		}
		return output;
	}

	// 获得N天后的时间
	public static Date getAfterNdaysDate(int n) {
		Date d = new Date();
		Long l = d.getTime() + n * 24 * 3600 * 1000;
		return new Date(l);
	}

	

}
